package com.sky.utils;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.sky.constant.MessageConstant;
import com.sky.exception.AddressParseException;
import com.sky.exception.OrderBusinessException;
import com.sky.properties.BaiduMapProperties;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.util.CollectionUtils;
import org.springframework.util.StringUtils;

import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.Map;

@Component
@Slf4j
public class BaiduMapUtil {
    /**
     * 默认ak
     * 选择了ak，使用IP白名单校验：
     * 根据您选择的AK已为您生成调用代码
     * 检测到您当前的ak设置了IP白名单校验
     * 您的IP白名单中的IP非公网IP，请设置为公网IP，否则将请求失败
     * 请在IP地址为xxxxxxx的计算发起请求，否则将请求失败
     */
    @Autowired
    private BaiduMapProperties properties;

    /**
     * 获取指定位置坐标
     * @param url 地理编码接口请求路径
     * @param paramMap 请求参数，里面需要设置ak，地址等参数
     * @return
     */
    public String getLocation(String url, Map<String, String> paramMap) {
        if (!StringUtils.hasLength(url) || CollectionUtils.isEmpty(paramMap)) {
            //地址参数为空，无法解析
            throw new AddressParseException(MessageConstant.ADDRESS_PARAM_IS_NULL);
        }

        //调用Http工具类发送请求，并获取响应结果：坐标
        String response = HttpClientUtil.doGet(url, paramMap);
        log.info("地址接口响应数据：{}",response);
        //将字符串解析为JsonObject对象，方便获取坐标属性
        /*
        响应的数据如下：要获取里面的lng和lat坐标，最好去文档那里看json格式响应数据，更直观
        {"status":0,"result":{"location":{"lng":116.30684538228411,"lat":40.057737278172179},
        "precise":1,"confidence":80,"comprehension":100,"level":"门址"}}
         */
        JSONObject object = JSON.parseObject(response);
        if (!object.get("status").equals(0)){
            //如果返回的status不是0，解析失败，返回接口的错误信息
            throw new AddressParseException(object.getString("message"));
        }
        JSONObject locationObject = object.getJSONObject("result").getJSONObject("location");

        String lat = locationObject.get("lat").toString();
        String lng = locationObject.get("lng").toString();

        return lat + "," + lng;//返回坐标，顺序不能错
    }

    /**
     * 获取商铺坐标，因为商铺一般固定，坐标最好提前算好，方便直接调用
     * @return
     */
    public String getShopLocation(String url) {
        //添加必要的参数
        Map<String, String> paramMap = new HashMap<>();
        paramMap.put("address", properties.getAddress());
        paramMap.put("ak", properties.getAK());
        paramMap.put("output", "json");
//        paramMap.put("callback", "showLocation");
        return getLocation(url, paramMap);
    }

    /**
     * 校验配送范围，是否可配送
     * @return
     */
    public boolean checkDistributionScope(String origin,String destination,String url){
        if (!StringUtils.hasLength(destination) || !StringUtils.hasLength(origin) || !StringUtils.hasLength(url)) {
            //地址参数为空，无法解析
            throw new AddressParseException(MessageConstant.ADDRESS_PARAM_IS_NULL);
        }

        //因为需要存入的坐标有先后顺序，所以用LinkedHashMap
        Map<String, String> paramMap = new LinkedHashMap<String, String>();
        paramMap.put("ak", properties.getAK());
        paramMap.put("origin",origin);//店铺坐标
        paramMap.put("destination",destination);//目的地坐标

        String response = HttpClientUtil.doGet(url, paramMap);//向接口发送get请求
        /*
        接口的响应的数据如下：像上面获取坐标一样，获取distance数据
        {"status": 0,"message": "ok","info": {"copyright": {"text": "@2023 Baidu - Data",
        "imageUrl": "http://api.map.baidu.com/images/copyright_logo.png"}}, "type": 2,"result": {
        "routes": [{"restrictions_status": 0,"restrictions_info": "",
          "distance": 17279,"duration": 5969,"steps": [
         */
        JSONObject object = JSON.parseObject(response);
//        log.info("骑行路线接口响应数据：{}",response);
        if (!object.get("status").equals(0)){//如果返回的status不是0，解析失败，返回接口的错误信息
            throw new AddressParseException(object.getString("message"));
        }

        JSONArray routesArray = object.getJSONObject("result").getJSONArray("routes");
        //获取到两个坐标间的距离
        Integer distance = (Integer) routesArray.getJSONObject(0).get("distance");

        return properties.getDistance() >= distance;//比较配送范围，返回结果:在配送范围内则返回true，反之false
    }

}
